\chapter{Pairs}
\section{Fonctionnement de base}

Lorsqu'il démarre, un pair commence par initialiser la connexion avec un tracker. Il envoie la socket ainsi obtenue dans un thread $thread\_tracker$ qui s'occupera de la réception des messages provenants du tracker et les traitera. \\

Ensuite il se met lui-même en écoute sur un port, en attendant qu'un ou plusieurs pairs se connecte à lui pour partager des fichiers ensemble. Chaque nouvelle socket ouverte est envoyée sur un thread $peer\_thread$ qui s'occupe de la réception et de l'envoi de messages au pair connecté.\\
Le pair peut donc établir de lui-même une connexion avec un autre pair ou bien recevoir une demande de connexion d'un autre pair. \\

Ce fonctionnement est décrit sur la figure \ref{peers}. 

\begin{center} 
\begin{figure}[!h]
   \caption{\label{peers} Dialogue d'un pair avec un tracker et d'autres pairs}
   \includegraphics[width=10cm]{echanges.png}
\end{figure}
\end{center} 

Puis il se met lui-même en écoute sur un port, en attendant qu'un ou plusieurs pairs se connecte à lui pour partager des fichiers ensemble. Chaque nouvelle socket ouverte est envoyée sur un thread $peer\_thread$ qui s'occupe de la réception et de l'envoi de messages au pair connecté. \\

Parallèlement à l'attente de connexion d'autres pairs, le pair attend également des ordres de l'utilisateur sur son entrée standard et il doit effectuer des mises à jour périodiques à destination des autres pairs et du tracker.

\section{Architecture}
Il n'y a pas de classes en C mais le projet est découpé en plusieurs éléments qui s'apparentent au concept de classe. \\

\subsection{Structure de données}

La structure de données décrite précédemment a été implémentée avec quatre structures dans un module $TAD$ (type abstrait de données : tad.h et tad.c) :
\begin{itemize}
\item $struct file$ représentant un fichier et contenant : sa clé, son nom, sa taille, la taille de ses pièces, ...)
\item $struct peer$ représentant un pair et contenant : son IP, son port d'écoute, son $file descriptor$, son thread de communication, la liste des fichiers leechés/seedés...)
\item $struct file\_list$ représentant une list de struct\_file
\item $struct peer\_list$ représentant une list de struct\_peer \\
\end{itemize}

Le pair qui exécute le programme utilise lui-même un $struct peer$ pour stocker certaines informations. Dans ce cas tous les attributs ne sont pas utilisés. On utilise nottamment la liste des fichiers leechés comme la liste des fichiers en cours de transfert avec d'autres pairs. Pour plus de praticité on l'appelle dans ce rapport $my\_leeched\_files$. \\

On définit ensuite un ensemble de fonctions qui opèrent sur ce TAD :
\begin{verbatim}
struct peer *add_peer(struct peer *p, struct peer *hashmap_peers);
/* ajout d'un pair au hashmap passé en paramètre */

struct peer *find_peer(char *key);
/* recherche d'un pair à partir de son couple IP/port */

struct file *add_file(struct file *p, struct file *hashmap_files);
/* ajout d'un fichier au hashmap passé en paramètre */

struct file *find_file(char *key, struct file *hashmap_files);
/* recherche d'un fichier à partir de sa clé */

struct file *find_file_subname(char *subname, struct file *hashmap_files);
/* recherche d'un fichier à partir d'une sous-chaîne de son nom */
\end{verbatim}

\subsection{Classes}

Conformément aux informations précédente, un pair possède une classe "peer" faisant office de "main", elle-même possédant :
\begin{itemize}
\item Deux hashmaps de fichiers seedés/leechés
\item D'autres attributs globaux, normalement lus depuis le fichier de configuration (adresses IP, port, etc ...)
\item Un unique thread de communication avec le tracker
\item zéro ou plusieurs threads de communication avec d'autres pairs \\
\end{itemize}

Cela est schématisé sur le diagramme \ref{classes}. \\

\begin{center} 
\begin{figure}[!h]
   \caption{\label{classes} Diagramme de "classes"}
   \includegraphics[width=14cm]{classes.png}
\end{figure}
\end{center} 

\section{Algorithme global de peer\_thread}

On rappelle que peer\_thread est la fonction exécutée par un pair $p$ pour dialoguer avec un second pair $p2$. La connexion peut avoir été établie indifféremment par l'un ou par l'autre, cela dépend du premier ayant besoin de télécharger une pièce. \\

Cette fonction effectue une boucle infinie d'écritures puis de lectures jusqu'à temps que l'un ou l'autre ferme la connexion ou se déconnecte suite à une erreur. Tout commence lorsque l'utilisateur demande Lors de sa phase d'écriture, $p$ vérifie dans sa liste des fichiers leechés ($my\_leeched\_files$ quels sont ceux qui sont leechés ou seedés par $p2$. S'il en trouve un ou plusieurs, il demande le buffermap de chacun d'eux à $p2$. La réception du buffermap sera effectuée plus tard lors d'une prochaine lecture. \\

Viennent ensuite le moment des lectures. Selon la commande reçue on compare le mot suivant avec le ou les mots attendus et on exécute les opérations en conséquence (peut être l'écriture de réponses).

\section{Accès concurrents}
Plusieurs thread pouvant lire et écrire dans les mêmes ressources, il convient de les protéger contre les accès concurrents. Nous avons utilisés les mutex pour implémenter cela. Un mutex est associé à la structure de données ainsi qu'à chaque socket (thread et pairs), verrouillés avant toute tentative d'accès puis déverrouillés à la fin.

\section{Calcul et mise à jour du bufferMap}

Le BufferMap est un tampon d'octets associé à un fichier $f$. Il indique quelles pièces un pair possède et partager ainsi que lesquelles il cherche à télécharger. Pour chaque bit $i$, le pair dispose de la pièce numéro $i+1$ si $i=1$, $0$ sinon. \\

La longueur $length(bm)$ du BufferMap en octets est ainsi :

$length(f)/length(pieces)+
\left\{
  \begin{array}{rcr}
    1$ si $length(f)$ $mod$ $length(pieces)$ $>$ $0\\
    0$ $sinon \\
  \end{array}
\right.$

Ici $length(f)$ est la taille de $f$ et $length(pieces)$ celle des pièces de $f$. \\

Pour savoir quellques sont les pièces que l'on peut demander à un pair (ie lesquelles il possède), on peut utiliser l'algorithme suivant, dont les indices sont représentés sur la figure \ref{bmap} :

\begin{verbatim}
Pour i de 0 à length(bm)-1 :
 c = ième caractère du buffermap bm;
 Pour j de 0 à 7 :
    d = ((1 << j) & c);
    si d != 0 alors 
        le pair dispose de la pièce p = j+1 + 8*i;
        demander le téléchargement de la pièce p;
\end{verbatim}

\begin{center} 
\begin{figure}[!h]
   \caption{\label{bmap} Indices de l'algorithme de détermination des pièces à télécharger}
   \includegraphics[width=12cm]{bmap.png}
\end{figure}
\end{center} 

A l'inverse, pour mettre à jour le buffermap après avoir télécharger la pièce $p$ :
\begin{verbatim}
bm[(p-1)/8] |= 1 << (p%8 - 1);
\end{verbatim}

\section{Mises à jour périodiques}

Périodiquement, chaque pair effectue deux mises à jour : l'une auprès du tracker et l'autre auprès des pairs connectés à lui. Ces mises à jour ont pour buts respectifs d'indiquer au tracker quels fichiers sont en cours de téléchargement (leeched) ou entièrement au téléchargement (seeded)  et indiquer aux pairs l'état du buffermap des fichiers leechés. \\

Il est possible d'utiliser un thread dédié à cet usage et qui passe son temps à sormir et à envoyer les mises à jour au moment opportun. Nous avons décidé d'utiliser au lieu de cela les timers proposés par UNIX. Au démarrage du pair un timer est créé pour envoyer un signal SIGALRM à lui-même périodiquement (cette valeur est disponible en attribut et est normalement lue depuis le fichier de configuration). Un gestionnaire de signal associé à SIGALRM fait appel aux deux fonctions de mises à jour auprès du tracker et de tous les pairs.\\

Les timers UNIX ont néanmoins un inconvénient c'est qu'ils créé une interruption prioritaire sur les appels système. Par exemple, si un timer est déclenché lorsqu'un thread est bloqué sur la lecture d'une socket, la lecture échouera avec le code d'erreur "Interrupted system call". Il faut donc relancer la lecture suite à cela, ce qui est tout à fait faisable. \\
